package com.xuanyang.dormrepair.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;

/**
 * @AUTHOR soft
 * @DATE 2019/5/19 11:19
 * @DESCRIBE
 */
@Slf4j
public class JwtKit {

    private static String secret = "XUANYANG519";
    private static Integer expire = 5 * 3600 * 24; // 5天

    /**
     * 生成一个token
     * @param username 用户名
     * @param password 加密后的密码
     */
    public static String sign(String username, String password) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        try {
            return JWT.create()
                    .withIssuer("TOKEN-签发者")
                    .withIssuedAt(new Date())  // 签证时间
                    .withSubject(username)     // 用户名
                    .withClaim("pwd", password) // 用户密码
                    .withExpiresAt(new Date(System.currentTimeMillis() + (expire * 1000))) // 过期时间
                    .sign(algorithm);
        } catch (RuntimeException e) {
            log.warn("签名失败！{}", e.getMessage());
            return "";
        }
    }

    /**
     * 验证token
     * @param token 被验证的token
     * @param username 用户名
     * @param password 加密后的密码
     */
    public static boolean verify(String token, String username, String password) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("TOKEN-签发者")
                    .withSubject(username)
                    .withClaim("pwd", password)
                    .build();
            verifier.verify(token);
            return true;
        } catch (Exception e) {
            log.warn("token验证失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 根据Token获取用户名 楼层+房间号
     */
    private static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getSubject();
        } catch (JWTDecodeException e) {
            log.warn("解码失败！{}", e.getMessage());
            return "";
        } catch (NullPointerException e) {
            log.warn("Token为null!");
            return "";
        }
    }

    /**
     * 根据token获取楼层号房间号
     */
    public static String[] getNos(String token) {
        String username = getUsername(token);
        if (StringUtils.isNotEmpty(username)) {
            return username.split("_");
        }
        return null;
    }

    /**
     * 加密 获取新密码用于保存在数据库
     * @param username 用户名
     * @param password 明文密码
     * @return 加密后的密码
     */
    public static String md5(String username, String password) {
        String str = username + password;
        try {
            MessageDigest md5 = MessageDigest.getInstance(Constants.MD5);
            //加密后的字符串
            byte[] src = md5.digest(str.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(src);
        } catch (NoSuchAlgorithmException e) {
            log.warn("MD5加密失败: {}", e.getMessage());
            return "";
        }
    }
}
